/**
 * The SPF global namespace object.
 * @class spf
 * @static
 */
if( typeof spf == 'undefined' ) {
    spf = {};
}

/**
 * Returns the namespace specified and creates it if it doesn't exist
 *
 * spf.namespace("property.package");
 * spf.namespace("spf.property.package");
 *
 * Either of the above would create spf.property, then
 * spf.property.package
 *
 * Be careful when naming packages. Reserved words may work in some browsers
 * and not others. For instance, the following will fail in Safari:
 *
 * spf.namespace("really.long.nested.namespace");
 *
 * This fails because "long" is a future reserved word in ECMAScript
 * @method namespace
 * @static
 * @param  {String} ns The name of the namespace
 * @return {Object}    A reference to the namespace object
 */
spf.namespace = function(ns) {

    if( !ns || !ns.length ) {
        return null;
    }

    var levels = ns.split('.');
    var nsobj = spf;

    // spf is implied, so it is ignored if it is included
    for (var i=(levels[0] == 'spf') ? 1 : 0; i<levels.length; ++i) {
        nsobj[levels[i]] = nsobj[levels[i]] || {};
        nsobj = nsobj[levels[i]];
    }

    return nsobj;
};


/***************************************************************************/
// Variable Type Functions
/***************************************************************************/

/**
 * Determines if the specified variable has been defined.
 * @public
 * @param    mixed   a   the variable to check.
 * @return   boolean
 */
spf.isUndefined = function(a) {
    return typeof a == 'undefined';
}

/**
 * Determines if the specified variable is null.
 * @public
 * @param    mixed   a   the variable to check.
 * @return   boolean
 */
spf.isNull = function(a) {
    return a === null;
}

/**
 * Determines if the specified variable is a boolean value.
 * @public
 * @param    mixed   a   the variable to check.
 * @return   boolean
 */
spf.isBoolean = function(a) {
    return typeof a == 'boolean';
}

/**
 * Determines if the specified variable is a valid integer or float.
 * @public
 * @param    mixed   a   the variable to check.
 * @return   boolean
 */
spf.isNumber = function(a) {
    return typeof a == 'number' && isFinite(a);
}

/**
 * Determines if the specified variable is a string.
 * @public
 * @param    mixed   a   the variable to check.
 * @return   boolean
 */
spf.isString = function(a) {
    return typeof a == 'string';
}

/**
 * Determines if the specified variable is an array.
 * @public
 * @param    mixed   a   the variable to check.
 * @return   boolean
 */
spf.isArray = function(a) {
    return this.isObject(a) && a.constructor == Array;
}

/**
 * Determines if the specified variable is a function.
 * @public
 * @param    mixed   a   the variable to check.
 * @return   boolean
 */
spf.isFunction = function(a) {
    return typeof a == 'function';
}

/**
 * Determines if the specified variable is an object.
 * @public
 * @param    mixed   a   the variable to check.
 * @return   boolean
 */
spf.isObject = function(a) {
    return (a && typeof a == 'object') || this.isFunction(a);
}

/**
 * Determines if the specified variable is empty.
 * @public
 * @param    mixed   a   the variable to check.
 * @return   boolean
 */
spf.isEmpty = function(o) {
    var i, v;
    if( this.isObject(o) ) {
        for (i in o) {
            v = o[i];
            if( this.isUndefined(v) && this.isFunction(v) ) {
                return false;
            }
        }
    }
    return true;
}

/***************************************************************************/
// General Functions
/***************************************************************************/
spf.navigate = function(controller, action, params, msg) {

   // if msg was specified then display a confirmation box and if
   // user clicks cancel then don't do anything
   if( msg ) {
      if( !confirm(msg) )
         return;
   }
   
   var url = '/';
   
   if( controller )
      url += '?url=' + controller;
   
   if( action )
      url += '/' + action;
   
   if( params )
      url += '/' + params;
   
   window.location = url;

} // navigate

spf.toggle_display = function( obj ) {
        
   obj = $(obj);
   
   // if using hidden class then replace class with actual display property
   if( obj.className == 'hidden' && (obj.style.display == '') )
      obj.style.display = 'none';
   
   switch( obj.style.display ) {
      
      case '':
         obj.style.display = 'none';
         break;
      
      case 'none':
         obj.style.display = 'block';
         break;
      
      case 'block':
         obj.style.display = 'none';
         break;
      
   } // switch
   
   return (obj.style.display == 'block');
   
} // toggle_display
 
/***************************************************************************/
// Prototype Shortcut
/***************************************************************************/

function $( obj ) {
  
   if (typeof obj == 'string')
      obj = document.getElementById(obj);
       
   return obj;
  
} // $
